#include "TLexico.h"

int TLexico_Crear(TLexico* al){
    int i;

    TSintactico_Crear(&al->analizadorSintactico);

    TLexico_setAnalizadorSintactico(al, &(al->analizadorSintactico));
    for(i=0;i<MAX_DATO;i++){
        al->caracteresProcesados[i]='\0';
        al->token.dato[i]='\0';
    };
    al->token.tipo = TOKEN_NULL;
    al->codigoUltimoError=0;
    al->ultchar=' ';
    return 0;
}

int TLexico_setAnalizadorSintactico(TLexico* al, TSintactico* as){ /*no tiene sentido si analizadorsintactico no es puntero, y para eso habria que usar memoria dinamica*/
    /*que paso aca??*/
    /* Se usa el memcpy para hacer una copia de lo apuntado por
       as a el TSintactico que se encuentra dentro de este TLexico */
    memcpy(&al->analizadorSintactico, as, sizeof(TSintactico));


    return 0;
}

int TLexico_PushChar(TLexico* al, char c){
    /* Concatena caracteres que viene recibiendo
       hasta que uno de los caracteres sea invalidos(donde devolveria error)
       o termina de armar el Token llama a pushToken y se lo pasa
       a el analizador sintactico */
    /*fijarse si ya se termino el token anterior o sigo con el mismo de antes*/
    /*tengo q definir el token aca*/
    /*Token* token = &al->token;*/

    int i=0;
    int codError=0;
    /*printf("%c",al->ultchar);*/
    /*printf("%d",strlen(al->caracteresProcesados));*/
    /*le asigno null a token.tipo despues de que manda el token con pushtoken */
    /*revisar que los strings tambien pueden tener numeros en el medio*/

    if(((c>0)&&(c<9))||((c>9)&&(c<32))){
        al->codigoUltimoError=CARACTER_INVALIDO + CORRECCION_CANTIDAD_ERRORES; /*error lexico, caracter invalido*/
        codError = 2;
    }
    else{  /*caracter valido*/
        if((al->token.tipo==TOKEN_STRING)&&(c!=34)){
            al->caracteresProcesados[strlen(al->caracteresProcesados)]=c;/*el char lo sumo al final de la cadena*/
            al->ultchar = c;
        }
        else{
            /*me fijo si es numero??*/
            /*es un numero*/
            if((isdigit(c)!=0)){
                if((al->token.tipo==TOKEN_NUMERO)&&(isdigit(al->ultchar)==0)){ /*teniamos n numero y se ingreso algo en el medio invalido*/
                    al->codigoUltimoError=CADENA_INVALIDA + CORRECCION_CANTIDAD_ERRORES;/*error lexico, cadena invalida, numero invalido*/
                    codError = 2;
                }
                else{
                    al->token.tipo = TOKEN_NUMERO;
                    al->caracteresProcesados[strlen(al->caracteresProcesados)]=c;
                    al->ultchar = c;
                }

            }
            else{
                if((c==44)||(c==58)||(c==93)||(c==91)||(c==125)||(c==123)){   /*44=',';58=':';93=']';91='[';125='}';123='{'*/
                    if((al->token.tipo==TOKEN_STRING)&&(isalpha(al->ultchar)!=0)){ /*si no cierran el string con comillas*/
                        al->codigoUltimoError=CADENA_INVALIDA + CORRECCION_CANTIDAD_ERRORES;/*error lexico, cadena invalida*/
                        codError = 2;
                    }
                    else{ /*armo tambien el token del numero si habia uno antes de este token*/
                        if(al->token.tipo==TOKEN_NUMERO){
                            for(i=0;i<strlen(al->caracteresProcesados);i++){
                                al->token.dato[i] = al->caracteresProcesados[i];
                            }
                            codError = TSintactico_PushToken(&al->analizadorSintactico, &al->token);
                            /*no reseteo e token a null?*/
                        }

                            /*dividir en los distintos casos posibles*/
                        if(c==123){
                            al->token.tipo = TOKEN_OBJETO_EMPIEZA;
                            al->token.dato[0] = c;
                        }
                        if(c==125){
                            /*armo el token*/
                            al->token.tipo = TOKEN_OBJETO_TERMINA;
                            al->token.dato[0] = c;
                        }
                        if(c==91){
                            /*armo el token*/
                            al->token.tipo = TOKEN_ARRAY_EMPIEZA;
                            al->token.dato[0] = c;
                        }
                        if(c==93){
                            /*armo el token*/
                            al->token.tipo = TOKEN_ARRAY_TERMINA;
                            al->token.dato[0] = c;
                        }
                        if(c==58){
                            /*armo el token*/
                            al->token.tipo = TOKEN_DOSPUNTOS;
                            al->token.dato[0] = c;
                        }
                        if(c==44){
                            /*armo el token*/
                            al->token.tipo = TOKEN_COMA;
                            al->token.dato[0] = c;

                        }
                        if(codError==0){ /*me fijo que el token numero no haya vuelto con error*/
                            /*llamo a PushToken*/
                            codError = TSintactico_PushToken(&al->analizadorSintactico, &al->token); /*termino el token*/
                            /*lo igualo a una constante y me fijo, si es 1 retorno error, si es 0, todo OK y sigo corriendo*/
                            /*cuando el lexico retorne error devuelvo 2 para diferenciarlo de los errores sintacticos*/
                            /*despues implemento la misma codificacion que utiliza el sintactico para los errores*/
                            /*si retorna 1 llamoa al getulterror del sint y si 2 al del lex. al del parser no se cuando llamarlo*/
                            al->token.tipo = TOKEN_NULL;
                            for(i=0;i<MAX_DATO;i++){
                                al->caracteresProcesados[i]= '\0';
                                al->token.dato[i]='\0';
                            }
                        }
                    }
                    al->ultchar = c;
                }
                else{
                    if(c==34){   /*si son comillas*/
                        if(al->token.tipo==TOKEN_STRING){
                            /*armo el token*/
                            for(i=0;i<strlen(al->caracteresProcesados);i++){
                                al->token.dato[i] = al->caracteresProcesados[i];/*arreglar*/
                            }
                            /*llamo a push token*/
                            codError = TSintactico_PushToken(&al->analizadorSintactico, &al->token); /*termino el token*/
                            /*igualarlo al al->codigoultimoError y despues veo si retur aca o dejo que llegue hasta el return del final*/
                            al->token.tipo = TOKEN_NULL;
                            for(i=0;i<MAX_DATO;i++){
                                al->caracteresProcesados[i]= '\0';
                                al->token.dato[i]='\0';
                            }
                        }
                        else{
                            al->token.tipo = TOKEN_STRING;
                        }
                        al->ultchar = c;
                    }
                    else{
                        if(isalpha(c)!=0){
                            /*tokens de true y false*/
                            if((c=='t')&&(al->token.tipo==TOKEN_NULL)){
                                al->token.tipo = TOKEN_TRUE;
                            } /*ver el temita de los tokens null, que parece que se envian*/
                            else{
                                if((c=='f')&&(al->token.tipo==TOKEN_NULL)){
                                    al->token.tipo = TOKEN_FALSE;
                                }
                                else{
                                    if(al->token.tipo==TOKEN_TRUE){
                                        if(!(((c=='r')&&(al->ultchar=='t'))||((c=='u')&&(al->ultchar=='r'))||((c=='e')&&(al->ultchar=='u')))){
                                            al->codigoUltimoError=CADENA_INVALIDA + CORRECCION_CANTIDAD_ERRORES;
                                            codError = 2;
                                        }
                                        else{
                                            if(c=='e'){
                                                /*mando token*/
                                                codError = TSintactico_PushToken(&al->analizadorSintactico, &al->token); /*termino el token*/
                                                /*igualarlo al al->codigoultimoError y despues veo si retur aca o dejo que llegue hasta el return del final*/
                                                al->token.tipo = TOKEN_NULL;
                                            }
                                        }
                                    }
                                    else{
                                        if(al->token.tipo==TOKEN_FALSE){
                                            if(!(((c=='a')&&(al->ultchar=='f'))||((c=='l')&&(al->ultchar=='a'))||((c=='s')&&(al->ultchar=='l'))||((c=='e')&&(al->ultchar=='s')))){
                                                al->codigoUltimoError=CADENA_INVALIDA + CORRECCION_CANTIDAD_ERRORES;
                                                codError = 2;
                                            }
                                            else{
                                                if(c=='e'){
                                                    /*mando token*/
                                                    codError = TSintactico_PushToken(&al->analizadorSintactico, &al->token); /*termino el token*/
                                                    /*igualarlo al al->codigoultimoError y despues veo si retur aca o dejo que llegue hasta el return del final*/
                                                    al->token.tipo = TOKEN_NULL;
                                                }

                                            }
                                        }
                                        else{
                                            if((c=='n')&&(al->token.tipo==TOKEN_NULL)&&(isalpha(al->ultchar)==0)){
                                                al->token.tipo = TOKEN_NULL;
                                            }
                                            else{
                                                if(al->token.tipo==TOKEN_NULL){
                                                    if(!(((c=='u')&&(al->ultchar=='n'))||((c=='l')&&(al->ultchar=='u'))||((c=='l')&&(al->ultchar=='l')))){
                                                        al->codigoUltimoError=CADENA_INVALIDA + CORRECCION_CANTIDAD_ERRORES;
                                                        codError = 2;
                                                    }
                                                    else{
                                                        if((c=='l')&&(al->ultchar=='l')){
                                                            /*mando token*/
                                                            codError = TSintactico_PushToken(&al->analizadorSintactico, &al->token); /*termino el token*/
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        al->ultchar = c;
                        if((c==9)&&(c==32)){  /*ni espacio ni TAB*/
                            if(al->token.tipo==TOKEN_NUMERO){
                                al->codigoUltimoError=CADENA_INVALIDA + CORRECCION_CANTIDAD_ERRORES; /*si hay espacios en medio de un numero*/
                                codError = 2;
                            }
                        }
                        else{
                            if((!al->token.tipo==TOKEN_FALSE)&&(!al->token.tipo==TOKEN_TRUE)){
                                al->codigoUltimoError=CADENA_INVALIDA + CORRECCION_CANTIDAD_ERRORES;/*cadena invalida, char invalido, que no esta adentro de un string*/
                                codError = 2;
                            }
                        }
                    }
                }
            }
        }
    }
    return codError;
}

int TLexico_terminarFlujo(TLexico* al){
    int i;
    /*Evaluar si este llamado va.
    TLexico_setAnalizadorSintactico(al, &(al->analizadorSintactico));
    */
    TSintactico_terminarFlujo(&al->analizadorSintactico);
    for(i=0;i<MAX_DATO;i++){
        al->caracteresProcesados[i]= '\0';
        al->token.dato[i]='\0';
    }
    al->token.tipo = TOKEN_NULL;
    al->codigoUltimoError=0;
    al->ultchar=' ';
    return 0;
}

int TLexico_getUltimoError(TLexico* al, int* codigo, char* mensaje){
    if(!al->codigoUltimoError){
    	TSintactico_getUltimoError(&al->analizadorSintactico,codigo,mensaje);
    }else {
    	(*codigo) = (al->codigoUltimoError);
   	    strcpy(mensaje,recuperarMensajeError(*codigo));
	}
    return 0;
}

int TLexico_setCallback(TLexico* l, int evento, void* tda_contexto, int(*callback)(const void*, int, const void*) ){
    /* Setea el callback al Lexico */
    TSintactico_setCallback(&l->analizadorSintactico, evento, tda_contexto, callback);
    /* Retorna codigo de OK */
    return CODIGO_OK;
}
